package com.exsun.gateway.jt809.codec;

import com.exsun.gateway.jt809.config.NettyClientConfig;
import exsun.jt808.data.util.parse.BitOperator;
import org.apache.log4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.ByteArrayOutputStream;

/**
 * JT809协议转义工具类
 */
@Component
public class JT809ProtocolUtils {

	private final static Logger log = Logger.getLogger(JT809ProtocolUtils.class);

	public JT809ProtocolUtils() {
	}

	/**
	 * 接收消息时转义<br>
	 * 
	 * <pre>
	 * 0x5a01 <====> 0x5b
	 * 0x5a02 <====> 0x5a
	 * 0x5e01 <====> 0x5d
	 * 0x5e02 <====> 0x5e
	 * </pre>
	 * 
	 * @param bs
	 *            要转义的字节数组
	 * @return 转义后的字节数组
	 * @throws Exception
	 */
	public static byte[] doEscape4Receive(byte[] bs) throws Exception {
		ByteArrayOutputStream baos = null;
		try {
			baos = new ByteArrayOutputStream();
			for (int i = 0; i <= bs.length - 1; i++) {
				if (bs[i] == 0x5a && bs[i + 1] == 0x01) {
					baos.write(0x5b);
					i++;
				} else if (bs[i] == 0x5a && bs[i + 1] == 0x02) {
					baos.write(0x5a);
					i++;
				} else if (bs[i] == 0x5e && bs[i + 1] == 0x01) {
					baos.write(0x5d);
					i++;
				} else if (bs[i] == 0x5e && bs[i + 1] == 0x02) {
					baos.write(0x5e);
					i++;
				} else {
					baos.write(bs[i]);
				}
			}
			return baos.toByteArray();
		} catch (Exception e) {
			throw e;
		} finally {
			if (baos != null) {
				baos.close();
				baos = null;
			}
		}
	}

	/**
	 * 
	 * 发送消息时转义<br>
	 * 
	 * <pre>
	 *  0x5b<====>0x5a01
	 *  0x5a<====>0x5a02
	 *  0x5d<====>0x5e01
	 *  0x5e<====>0x5e02
	 * </pre>
	 * 
	 * @param bs
	 *            要转义的字节数组
	 * @return 转义后的字节数组
	 * @throws Exception
	 */
	public static byte[] doEscape4Send(byte[] bs) throws Exception {
		ByteArrayOutputStream baos = null;
		try {
			baos = new ByteArrayOutputStream();
			for (int i = 0; i < bs.length; i++) {
				if (bs[i] == 0x5b) {
					baos.write(0x5a);
					baos.write(0x01);
				} else if (bs[i] == 0x5a) {
					baos.write(0x5a);
					baos.write(0x02);
				} else if (bs[i] == 0x5d) {
					baos.write(0x5e);
					baos.write(0x01);
				} else if (bs[i] == 0x5e) {
					baos.write(0x5e);
					baos.write(0x02);
				} else {
					baos.write(bs[i]);
				}
			}
			return baos.toByteArray();
		} catch (Exception e) {
			throw e;
		} finally {
			if (baos != null) {
				baos.close();
				baos = null;
			}
		}
	}

	/**
	 * 
	 * @param key
	 * @param data
	 */
	public static void accMsgEncrypt(int key, byte[] data, int IA1, int M1, int IC1) {
		int idx = 0;
		if (key == 0)
			key = 1;
		while (idx < data.length) {
			if (key < 0) {
				long k = 4294967296l + key;
				key = (int) (IA1 * (k % M1) + IC1);
			} else
				key = IA1 * (key % M1) + IC1;
			data[idx++] ^= (byte) ((key >> 20) & 0xFF);
		}
	}

	// 生成消息头
	public static byte[] generateMsgHeader(int msgId, int bodyLength, int centerid, int flowId)
			throws Exception {
		ByteArrayOutputStream baos = null;
		try {
			baos = new ByteArrayOutputStream();
			// 1. 消息长度(4)
			baos.write(BitOperator.integerTo4Bytes(1 + 22 + bodyLength + 2 + 1));
			// 2. 消息流水号(4)
			baos.write(BitOperator.integerTo4Bytes(flowId));
			// 3. 消息ID (2)
			baos.write(BitOperator.integerTo2Bytes(msgId));
			// 4.接入码(4)
			baos.write(BitOperator.integerTo4Bytes(centerid));
			// 5.（8bytes）版本号0x010000;加密标识：0x00;key:0x00000000
			baos.write(new byte[] { 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 });
			return baos.toByteArray();
		} finally {
			if (baos != null) {
				baos.close();
			}
		}
	}

}
